package com.eva.databuilder.builders.cms;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.eva.cms.biz.category.vo.CmsCategoryNodeVO;
import com.eva.dao.cms.model.CmsTemplate;
import com.eva.databuilder.builders.AbstractTemplateDataBuilder;
import com.eva.databuilder.bo.TemplateDataParameters;
import com.eva.framework.common.constants.ResponseStatus;
import com.eva.framework.common.exception.BusinessException;
import com.eva.service.common.FreemarkerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 栏目数据构建器基类
 */
@Slf4j
@Component
public abstract class BaseCategoryTreeBuilder extends AbstractTemplateDataBuilder<List<CmsCategoryNodeVO>> {

    private static final String PARAMETER_CATEGORY_UID = "categoryUid";

    @Resource
    private FreemarkerService freemarkerService;

    /**
     * 补充常规栏目的访问地址，将访问地址
     *
     * @param nodes 栏目节点
     */
    protected void paddingCategoryUri (List<CmsCategoryNodeVO> nodes, Map<Integer, CmsTemplate> cmsTemplateMap) {
        for (CmsCategoryNodeVO node : nodes) {
            // 常规栏目访问地址为模板的访问地址
            if (node.getTemplateId() != null) {
                CmsTemplate template = cmsTemplateMap.get(node.getTemplateId());
                if (template == null) {
                    throw new RuntimeException("栏目配置有误！");
                }
                node.setUri(cmsTemplateMap.get(node.getTemplateId()).getAccessUri());
            }
            if (!CollectionUtils.isEmpty(node.getChildren())) {
                this.paddingCategoryUri((List<CmsCategoryNodeVO>)node.getChildren(), cmsTemplateMap);
            }
        }
    }

    /**
     * 获取栏目绑定的模板ID集
     *
     * @param nodes 栏目节点
     * @param templateIds 模板ID集，获取后保存到此
     */
    protected void getTemplateIds (List<CmsCategoryNodeVO> nodes, Set<Integer> templateIds) {
        for (CmsCategoryNodeVO node : nodes) {
            if (node.getTemplateId() != null) {
                templateIds.add(node.getTemplateId());
            }
            if (!CollectionUtils.isEmpty(node.getChildren())) {
                this.getTemplateIds((List<CmsCategoryNodeVO>)node.getChildren(), templateIds);
            }
        }
    }

    /**
     * 编译栏目访问路径，得到最终栏目的访问地址
     *
     * @param nodes 栏目节点
     * @param parameters 模板参数
     */
    protected void compileCategoryUri (List<CmsCategoryNodeVO> nodes, TemplateDataParameters parameters) {
        for (CmsCategoryNodeVO node : nodes) {
            if (StringUtils.isNotBlank(node.getUri())) {
                // 拷贝参数
                TemplateDataParameters copyParameters =
                        JSON.parseObject(JSON.toJSONString(parameters), TemplateDataParameters.class);
                // 补充当前栏目唯一标识
                copyParameters.put(PARAMETER_CATEGORY_UID, node.getUid());
                // 如果栏目存在配置，则将预设的参数配置写入参数，供编译访问路径使用
                if (StringUtils.isNotBlank(node.getTemplateParameters())) {
                    JSONObject targetPresetParametersJson = null;
                    try {
                        targetPresetParametersJson = JSON.parseObject(node.getTemplateParameters());
                    } catch (JSONException ignore) {}
                    if (targetPresetParametersJson == null) {
                        log.warn("无法正确解析栏目 " + node.getTitle() + " 的模板参数");
                    }
                    if (targetPresetParametersJson != null) {
                        for (String key : targetPresetParametersJson.keySet()) {
                            List<TemplateDataParameters.PresetParameter> presetParameters =
                                    JSONArray.parseArray(targetPresetParametersJson.getString(key), TemplateDataParameters.PresetParameter.class);
                            for (TemplateDataParameters.PresetParameter presetParameter : presetParameters) {
                                copyParameters.assignIfNotEmpty(presetParameter.getName(), presetParameter.getValue());
                            }
                        }
                    }
                }
                try {
                    String compiledUri = freemarkerService.compile(node.getUri(), node.getUri(), copyParameters);
                    node.setUri(compiledUri);
                } catch (BusinessException e) {
                    log.error("编译栏目路径失败！栏目: {}, 栏目路径表达式: {}", node.getType(), node.getUri());
                    if (e.getCode().equals(ResponseStatus.TEMPLATE_ERROR.getCode())) {
                        throw new RuntimeException("栏目配置有误！");
                    }
                }
            }
            if (!CollectionUtils.isEmpty(node.getChildren())) {
                this.compileCategoryUri((List<CmsCategoryNodeVO>)node.getChildren(), parameters);
            }
        }
    }
}
